package org.dh2580.netty.demo.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

/**
 * @Author: hao.deng
 * @Date: 2019/3/20-下午2:21
 */
public class TimeServer {
    public static void main(String[] args) throws Exception {
        new Thread(new TimeServerHandler(8080)).start();
    }

    public static class TimeServerHandler implements Runnable {
        private Selector selector;

        private ServerSocketChannel serverChannel;

        private volatile boolean stop;

        public TimeServerHandler(int port) throws Exception {
            //创建 Selector
            selector = Selector.open();

            //创建服务端 Channel
            serverChannel = ServerSocketChannel.open();
            serverChannel.configureBlocking(false);
            serverChannel.socket().bind(new InetSocketAddress(port), 1024);

            //将服务端 Channel 绑定到 Selector 上
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        }

        @Override
        public void run() {
            try {
                innerRun();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void innerRun() throws Exception {
            while (!stop) {

                //选择已就绪的key等待3000ms
                selector.select(3000);

                Set<SelectionKey> selectedKeys = selector.selectedKeys();

                Iterator<SelectionKey> it = selectedKeys.iterator();

                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    //处理响应的key
                    handleInput(key);

                    it.remove();
                }
            }

            if (selector != null) {
                selector.close();
            }
        }

        private void handleInput(SelectionKey key) throws Exception {
            if (!key.isValid()) {
                return;
            }

            if (key.isAcceptable()) {
                //提取先前注册的服务端Channel
                ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();

                //接收到套嵌字Channel
                SocketChannel socketChannel = serverChannel.accept();
                socketChannel.configureBlocking(false);

                //注册到Selector上
                socketChannel.register(selector, SelectionKey.OP_READ);
            }

            if (key.isReadable()) {
                SocketChannel socketChannel = (SocketChannel) key.channel();

                ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                //读取数据到buffer中
                int readBytes = socketChannel.read(readBuffer);
                if (readBytes <= 0) {
                    return;
                }

                readBuffer.flip();

                //将buffer中的数据提取出至byte数组
                byte[] bytes = new byte[readBuffer.remaining()];
                readBuffer.get(bytes);

                String body = new String(bytes, "UTF-8");
                System.out.println("The time server receive order : " + body);

                String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date().toString() : "BAD ORDER";

                //将响应数据刷出去
                doWrite(socketChannel, currentTime);
            }
        }

        private void doWrite(SocketChannel socketChannel, String response) throws Exception {
            byte[] bytes = response.getBytes("UTF-8");
            ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
            writeBuffer.put(bytes);
            writeBuffer.flip();
            socketChannel.write(writeBuffer);
        }

        public void stop() {
            this.stop = true;
        }
    }

}
